package serv

import (
	"d-serv-go/server/core/bean"
	"d-serv-go/server/core/config"
	"d-serv-go/server/core/consts"
	"d-serv-go/server/core/db"
	"d-serv-go/server/core/log"
	"errors"
	"fmt"
	"github.com/bitly/go-simplejson"
	"io/ioutil"
	"reflect"
	"strings"
)

// 存储服务类->获取服务类实例的func，第一次加载服务时调用一次
var servReg = map[string]ServFunc{}

// 存储服务类->已经实例化的对象
var servMap = map[string]*ServAop{}

var servJsonMap = map[string]*simplejson.Json{}

// 为了动态调用
type ServFunc func() ServAop

type servMgr struct {
}

func NewServMgr() *servMgr {
	return &servMgr{}
}

// 注册服务的实现类
func RegistServ(serv string, newFunc ServFunc) {
	servReg[serv] = newFunc
	// log.Info("regist serv:", serv, newFunc)
}

func (m *servMgr) Act(paramBean *db.ParamBean) *bean.OutBean {
	outBean := m.Act3(paramBean.GetServId(), paramBean.GetAct(), paramBean)
	return outBean
}

func (m *servMgr) Act3(servId string, act string, paramBean *db.ParamBean) *bean.OutBean {
	result := bean.NewOutBean()
	context := db.Ctx()
	// 根据服务编码，找到对应的JSON
	servBean, _ := ServUtils.GetServBean(servId)
	bTrans := paramBean.GetTransFlag()
	//
	ds := servBean.GetDataSource()
	if !bTrans && len(ds) > 0 { //如果没启用事务且使用自定义数据源，则强制启用事务
		bTrans = true
	}
	// 事务处理
	if bTrans {
		context.BeginTx(ds)
		defer context.EndTx()
		paramBean.SetTransFlag(false) //清除参数的事务标志，确保不被误传递
	}
	// 默认时CommServ
	servClass := "CommonServ"
	class := strings.Split(servBean.GetStr("SERV_CLASS"), ".")
	if len(class) > 0 {
		servClass = class[len(class)-1]
	}
	result = InvokeObjectMethod(servClass, act, paramBean)

	// TODO end of transaction
	return result
}

// call server instance
func InvokeObjectMethod(servClass string, methodName string, paramBean *db.ParamBean) *bean.OutBean {
	// 获取服务的监听类对象
	servVar, ok := getInstance(servClass)
	if !ok {
		outBean := bean.NewOutBean()
		outBean.SetError(fmt.Sprintf("没有找到监听类％s", servClass))
		return outBean
	}
	servInstance := reflect.ValueOf(*servVar)
	// 查找方法
	method := servInstance.MethodByName(methodName)
	// 如果没有找到方法
	if !method.IsValid() {
		outBean := bean.NewOutBean()
		return outBean.SetError("没有找到服务的方法")
	}
	if servInstance.Type().String() != "*serv.CommServ" {
		// 如果自定义类，带入当前对象，为了调用Before*、After*
		paramBean.Set(consts.INSTANCE, *servVar)
	}
	inputs := []reflect.Value{reflect.ValueOf(paramBean)}
	callValues := method.Call(inputs)
	return callValues[0].Interface().(*bean.OutBean)
}

func isBlank(value reflect.Value) bool {
	switch value.Kind() {
	case reflect.String:
		return value.Len() == 0
	case reflect.Bool:
		return !value.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return value.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return value.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return value.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return value.IsNil()
	}
	return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
}

// 构建一个实例，根据类名找到一个对象
func getInstance(servClass string) (*ServAop, bool) {
	if inst, ok := servMap[servClass]; ok {
		return inst, true
	} else {
		// find the serv factory func
		if servFunc, ok := servReg[servClass]; ok {
			inst := servFunc()
			servMap[servClass] = &inst
			return &inst, true
		} else {
			if inst, ok := servMap["CommonServ"]; ok {
				return inst, true
			}
			servFunc := servReg["CommonServ"]
			inst := servFunc()
			servMap[servClass] = &inst
			return &inst, true
		}
	}
}

func (u *servMgr) GetServJson(servId string) (*simplejson.Json, error) {
	json, ok := servJsonMap[servId]
	if ok {
		return json, nil
	} else {
		// 尝试加载json
		data, err := ioutil.ReadFile(config.Instance.AppDir + "/docs/SY_SERV/" + servId + ".json")
		if err != nil {
			log.Error("没有找到服务[%v]的json", servId)
			return nil, errors.New("没有找到服务的json")
		}
		json, err := simplejson.NewJson([]byte(data))
		if err != nil {
			log.Error("服务[%v]的json，格式有问题", servId)
			return nil, errors.New(fmt.Sprintf("服务[%v]的json，格式有问题", servId))
		}
		servJsonMap[servId] = json
		return json, nil
	}
}

